package us.versus.them.libounce;

import flash.display.Sprite;
import flash.display.Graphics;

class Ball extends Sprite {
	public var dx : Float;
	public var dy : Float;
	var color : UInt;
	var line : Line;

	public static var BOUNCE_LOSS = 0.9;
	public static var GRAVITY = 0.5;

	public function new( x:Float, y:Float, ?color:UInt ) {
		super();
		this.x = x;
		this.y = y;
		this.dx = 0;
		this.dy = 0;
		if ( null == color ) {
			color = Math.floor( 0xFFFFFF * Math.random() );
		}
		this.color = color;
		this.line = new Line();
	}

	//var xcl : Line;
	//var xangle: Float;

	public function move( lines:haxe.FastList< Line >, width:Float, height:Float ) {

		//if ( null != xcl ) return;

		this.dy += GRAVITY;

		var when = Line.NO_TIME;
		var closest:Line = null;

		this.line.ball( this );
		this.line.wrap( width, height );

		for ( line in lines ) {
			var t = line.fullInteresction( this.line );
			if ( t < when ) {
				when = t;
				closest = line;
			}
		}

		if ( null == closest ) {
			this.x += this.dx;
			this.y += this.dy;
		} else {
//xcl = closest;
			bounce( when, closest );
		}

		// not so fast...
		if ( this.x < 0 || this.x > width || this.y > height ) {
			reset( width, height );
		}
	}

	public function draw( graphics:Graphics, width:Float, height:Float ) {
		var x = Line.wrapAround( this.x, width );
		var y = Line.wrapAround( this.y, height );
		graphics.lineStyle( 1, 0x0000FF );
		graphics.beginFill( color );
		graphics.drawCircle( x, y, 10 );
		graphics.endFill();
/*
		if ( null != xcl ) {
			graphics.lineStyle( 4, 0xFF0000 );
			graphics.moveTo( xcl.x0, xcl.y0 );
			graphics.lineTo( xcl.x1, xcl.y1 );

			var f = 200.0;

			graphics.lineStyle( 8, 0x0000FF );
			graphics.moveTo( x, y );
			graphics.lineTo( x + dx * f, y + dy * f);

			graphics.lineStyle( 8, 0x00FF00 );
			graphics.moveTo( x, y );
			graphics.lineTo( x + Math.cos( xangle ) * f, y + Math.sin( xangle ) * f );
		}
*/
	}


	private function bounce( when:Float, closest:Line ) {
		// TODO: handle second bounce?

		// move to point of intersection
		this.x += this.dx * when * BOUNCE_LOSS;
		this.y += this.dy * when * BOUNCE_LOSS;

		// figure out the angle of the bounce
		// cos(angle) = a.len * b.len * dot(a,b)
		var len = this.line.length();
		var ab = len * closest.length();
		if ( 0 == ab ) ab = 1; // LAME!
		var dot = ( this.line.xdiff * closest.xdiff + this.line.ydiff * closest.ydiff );
		var cos = dot / ab;
		var angle = Math.acos( cos );

//xangle = angle;

		if ( false ) {
			if( angle < 11 / 7.0 ) {
				angle -= 11.0 / 7.0; // add 90 degrees
			} else {
				angle += 11.0 / 7.0; // add 90 degrees
			}
		} else {
			angle = -angle;
			//f (angle<0) angle+=Math.PI*2;
			//f (angle>Math.PI) angle-=Math.PI;
		}

		var sin = Math.sin( angle );
		cos = Math.cos( angle );

		// bounce the ball to the new position
		var dist = ( 1 - when ) * len + 2;
		

		this.dx = dist * cos;
		this.dy = dist * sin;
	}

	private function reset( width:Float, height:Float ) {
		this.y = height - this.y;
		this.x = Math.random() * width;
		this.dx = 0;
		this.dy = 0;
	}


}
